#include "Control.hpp"
#include <signal.h>
#include <functional>

ns_control::Control* CTL_PTR = nullptr;
void SigHandler(int)
{
    CTL_PTR->ReOnHost();
}

static const string LogFile = "/var/log/OJ_server.log";
int main(int argc, char *argv[])
{
    static const string WebRoot = "./wwwroot";

    //一般的上线服务都是固定端口的，此处只是测试
    if (argc != 2)
    {
        cout << "Usage:\n\t./Compile_server Port" << endl;
        return -1;
    }

    // 设置守护进程
    daemon(1, 1);
    // 对日志(标准输出)做重定向
    int fd = open(LogFile.c_str(), O_WRONLY | O_CREAT | O_APPEND, 0666);
    if (fd == -1)
    {
        cout << "创建/写入日志文件权限不足:" << LogFile << endl;
        exit(-1);
    }
    dup2(fd, 1);

    ns_control::Control ctl(&CTL_PTR); // 控制器

    // 重启离线Compile_server主机
    signal(SIGQUIT, SigHandler);

    httplib::Server svr;
    // 设置web根目录
    svr.set_base_dir(WebRoot);

    // 服务注册
    // 1. 获取题目列表
    svr.Get(R"(/List)", [&](const httplib::Request &rst, httplib::Response &rse)
            { rse.set_content(ctl.GetListHtml(), "text/html"); });
    // 2. 具体的题目编写
    //  /question/1 正则匹配
    svr.Get(R"(/Question/(\d+))", [&](const httplib::Request &rst, httplib::Response &rse)
            {
        string id = rst.matches[1];
        rse.set_content(ctl.GetOneQuestionHtml(id), "text/html"); });
    // 3. 提交运行
    svr.Post(R"(/Judge/(\d+))", [&](const httplib::Request &rst, httplib::Response &rse)
             {
        string submit = rst.body;
        string id = rst.matches[1];
        rse.set_content(ctl.Judge(id, submit), "text/plain;"); });

    // 处理未匹配到的路由(正则表达式，匹配任意路径)
    svr.Get(R"(.*)", [](const httplib::Request &rst, httplib::Response &rse)
            {
        string tmp = ns_util::FileUiil::ReadFile(WebRoot+"/404.html");
        rse.status = 404;
        rse.set_content(tmp, "text/html"); });

    // 监听启动服务
    svr.listen("0.0.0.0", atoi(argv[1]));

    // test - Model
    /*
    ns_model::Model md;
    set<ns_model::Info> st = md.GetList();
    for (auto& e : st)
    {
        cout << e._id << " " << e._title << " " << e._level << endl;
    }

    ns_model::Question qsn;
    md.GetOneQuestion(1, qsn);
    cout << qsn._cpu_limit << " " << qsn._mem_limit << endl;
    cout << qsn._desc << endl << qsn._show << qsn._to_be_merged;
    */

    return 0;
}